#include "Field.h"

#include "BasicTypes.h"
#include "ClassMeta.h"
#include "Type.h"

namespace MOE
{
    namespace Core
    {
		const Field Field::kInvalid = Field();

		// Default constructor. Constructs an invalid field that has Nil class as its parent class.
		Field::Field()
			: mParentClass(ClassMeta::kNil)
			, mFieldName("")
			, mType(Type::kDefault)
			, mStartingOffset(0)
		{
		}

        // Constructs the field under parentClass.
        Field::Field(const ClassMeta& parentClass, const char8* fieldName, const Type& fieldType, tSize startingOffset)
			: mParentClass(parentClass)
			, mFieldName(fieldName)
			, mType(fieldType)
			, mStartingOffset(startingOffset)
		{
		}

		// Checks if this is not a default-constructed "invalid" field.
		bool Field::IsValid() const
		{
			return !mParentClass.IsNil();
		}
		
		// Get the reference of the field from classObject.
		tUntypedConstRef Field::GetFieldRef(tUntypedConstRef classObject) const
		{
			return (static_cast<const int8*>(classObject) + mStartingOffset);
		}

		tUntypedRef Field::GetFieldRef(tUntypedRef classObject) const
		{
			return (static_cast<int8*>(classObject) + mStartingOffset);
		}

		// Read field value from object, and write it to destination. Destination must be able to hold the size of Type.
		void Field::ReadValue(tUntypedConstRef classObject, tUntypedRef valueDestination) const
		{
			tUntypedConstRef fieldReference = GetFieldRef(classObject);
			mType.CopyValue(fieldReference, valueDestination);
		}

		// Write the value from source to the field on object.
		void Field::WriteValue(tUntypedConstRef valueSource, tUntypedRef classObject) const
		{
			tUntypedRef fieldReference = GetFieldRef(classObject);
			mType.CopyValue(valueSource, fieldReference);
		}
	}
}
